class Zombie extends Sprite
{
  private PVector direction;
  private Terrain terrain;
  private Humanoid _shape;
  
  private final float ZOMBIE_SPEED = .2f;
  private final int ATTACK_DELAY = 30;
  private final int STAT_MULTIPLIER = 4;
  private final float ZOMBIE_SIZE = 3;
  private int attackDelayCounter = 0;
  private Player target;
  private ArrayList<Zombie> zombies;
  
  private boolean movingFlag;
  private boolean attacking;
  
  public Zombie(int level, Player target, PVector location, Terrain terrain, ArrayList<Zombie> zombies)
  {
    this.target = target;
    this.location = location;
    this.direction = PVector.sub(target.getLocation(), location);
    this.terrain = terrain;
    this.spriteSize = ZOMBIE_SIZE * 1.5;
    attacking = false;
    movingFlag = true;
    this.zombies = zombies;
    
    damage = 5;
    
    _shape = new Humanoid(this.location, this.direction, ZOMBIE_SIZE);
    updateStats(level);
  }
  
  public void draw()
  {
   if (!paused)
   {
      updateDirection();
      if (!attacking)
        updateLocation();
   }
    drawSphere();
  }
  
  private void drawSphere()
  {
//    fill(204, 85, 0);
    _shape.draw();
  }
  
  private void updateDirection()
  {
    
    // weight 1 to move in same direction
    //PVector newDirection = new PVector(direction.x, direction.y, direction.z);
    PVector newDirection = new PVector(0,0,0);
    
    //adjust based on player posistion
    PVector playerDirection = PVector.sub(target.getLocation(), location);
    playerDirection.y = 0;
    float playerMag = playerDirection.mag();
    if(playerMag>0 && movingFlag)
    {      
      float playerAttractWeight = 100*(1/playerMag);
      float playerRepelWeight = -600*(1/(playerMag*playerMag)); 
      newDirection = PVector.add(newDirection, PVector.mult(playerDirection, playerAttractWeight));
      newDirection = PVector.add(newDirection, PVector.mult(playerDirection, playerRepelWeight)); 
      if (playerMag < 10)
      {
        movingFlag = false;
        attack(true);
      }
    }  
    else if (playerMag >= 10 && !movingFlag)
    {
      movingFlag = true;
      attack(false); 
    }
    //print("a: " + playerAttractWeight + "\tr: " + playerRepelWeight + "\n"); 
     
    
   
   //adjust based on zombie position
     for(Zombie zombie : zombies)
    {
     PVector zombieDirection = PVector.sub(zombie.getLocation(), location);
     zombieDirection.y = 0;
     float zombieMag = zombieDirection.mag();
       if(zombieMag>1 && zombieMag < 100 && movingFlag)
       {
         float zombieAttractWeight = zombieMag/100;
         float zombieRepelWeight = -150*(1/(zombieMag*zombieMag));
         newDirection = PVector.add(newDirection, PVector.mult(zombieDirection, zombieAttractWeight));
         newDirection = PVector.add(newDirection, PVector.mult(zombieDirection, zombieRepelWeight)); 
       }
    }   

    
    direction = newDirection;
    direction.normalize();
    if (movingFlag)
      _shape.updateDirection(direction);
  }
  
  private void updateLocation()
  {
     PVector change = PVector.mult(direction, ZOMBIE_SPEED);
     change.add(location);
     location = terrain.update(change.x, change.z);
     location.y -= 4;
     _shape.updateLocation(location);
  }
  
  public void updateStats(int level) 
  {
    health = int(health * level / STAT_MULTIPLIER);
    damage = int(damage + level / STAT_MULTIPLIER);
  }
  
  public boolean canAttack()
  {
    if (attackDelayCounter == ATTACK_DELAY)
    {
      attackDelayCounter = 0;
      return true;
    }
    attackDelayCounter++;
    return false;
  }
  
  private void attack(boolean isAttacking)
  {
   attacking = isAttacking; 
   _shape.isAttacking(isAttacking);
  }
  
}
